package com.axend.vetwavve.helper

import android.graphics.Bitmap
import android.util.Log
import org.opencv.android.OpenCVLoader
import org.opencv.android.Utils
import org.opencv.core.Core
import org.opencv.core.Mat
import org.opencv.core.MatOfPoint
import org.opencv.core.Point
import org.opencv.core.Rect
import org.opencv.core.Scalar
import org.opencv.core.Size
import org.opencv.imgproc.Imgproc

class TrackerHelper {
    init {
        if (OpenCVLoader.initLocal()) {
            Log.i("TrackerHelper", "OpenCV loaded successfully")
        } else {
            Log.e("TrackerHelper", "OpenCV initialization failed!")
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    private var previousFrame: Mat? = null
    private var currentFrame: Mat? = null
    private var kernel: Mat? = null
    private var frameCount = 0

    /**
     * process Infrared Thermal Imaging Target Tracking
     */
    fun processThermalImagingTargetTracking(p0: Bitmap?): Bitmap? {
        previousFrame = previousFrame ?: Mat()
        currentFrame = currentFrame ?: Mat()
        kernel = kernel ?: Imgproc.getStructuringElement(Imgproc.MORPH_RECT, Size(3.0, 3.0));

        frameCount++
        if (frameCount % 3 == 0) {
            if (previousFrame!!.empty()) {
                Utils.bitmapToMat(p0, previousFrame)
                return p0;
            }
            Utils.bitmapToMat(p0, currentFrame)

            val diff = Mat()
            val gray1 = Mat()
            val gray2 = Mat()
            Imgproc.cvtColor(previousFrame, gray1, Imgproc.COLOR_RGBA2GRAY);
            Imgproc.cvtColor(currentFrame, gray2, Imgproc.COLOR_RGBA2GRAY);
            Core.absdiff(gray1, gray2, diff);

            Imgproc.threshold(diff, diff, 30.0, 255.0, Imgproc.THRESH_BINARY)
            Imgproc.dilate(diff, diff, kernel, Point(-1.0, -1.0), 3)

            val contours: List<MatOfPoint> = ArrayList()
            Imgproc.findContours(
                diff,
                contours,
                Mat(),
                Imgproc.RETR_EXTERNAL,
                Imgproc.CHAIN_APPROX_SIMPLE
            )


            if (contours.isNotEmpty()) {
                var maxArea = 0.0
                var largestContour: Rect? = null
                for (contour in contours) {
                    val area = Imgproc.contourArea(contour)
                    if (area > maxArea && area < 10000) {
                        maxArea = area
                        largestContour = Imgproc.boundingRect(contour)
                    }
                }

                if (largestContour != null) {
                    val x = largestContour.x
                    val y = largestContour.y
                    val w = largestContour.width
                    val h = largestContour.height
                    if (maxArea > 100) {
                        Imgproc.rectangle(
                            currentFrame,
                            Point(x.toDouble(), y.toDouble()),//largestContour.tl()
                            Point((x + w).toDouble(), (y + h).toDouble()),//largestContour.br()
                            Scalar(255.0),
                            2
                        )
                    }
                }
            }

            diff.release()
            gray1.release()
            gray2.release()
            previousFrame!!.release()
            previousFrame = currentFrame!!.clone()


            val processedBitmap = Bitmap.createBitmap(
                currentFrame!!.cols(),
                currentFrame!!.rows(),
                Bitmap.Config.ARGB_8888
            )
            Utils.matToBitmap(currentFrame, processedBitmap)

            return processedBitmap
        } else {
            currentFrame!!.release()
            Utils.bitmapToMat(p0, currentFrame)
            previousFrame!!.release()
            Utils.bitmapToMat(p0, previousFrame)
            return p0
        }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
}
